package com.zy.chat.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zy.chat.dto.LoginFormDTO;
import com.zy.chat.entity.*;
import com.zy.chat.mapper.CommentMapper;
import com.zy.chat.mapper.DynamicMapper;
import com.zy.chat.mapper.FollowMapper;
import com.zy.chat.mapper.UserMapper;
import com.zy.chat.service.DynamicService;
import com.zy.chat.service.IFollowService;
import com.zy.chat.service.UserService;
import com.zy.chat.util.UserHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import static com.zy.chat.util.RedisContants.*;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zy
 * @date 2023/5/17 17:13
 */

@Service
public class DynamicServiceImpl extends ServiceImpl<DynamicMapper, Dynamic> implements DynamicService {


    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserService userService;
    @Autowired
    private  DynamicMapper dynamicMapper;

    @Autowired
    private IFollowService iFollowService;
    @Override
    public int insert(Dynamic dynamic) {
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        dynamic.setSendTime(timestamp);
        int isSuccess = dynamicMapper.insert(dynamic);
        if(isSuccess!=1){
            return 0;
        }
        String username=UserHolder.getUser().getUsername();
        List<Follow> followList = iFollowService.query().eq("follow_username", username).list();
        for (Follow f:followList) {
            String key=FEED+f.getUsername();
            Boolean add = redisTemplate.opsForZSet().add(key, dynamic.getId().toString(), System.currentTimeMillis());
        }
        return 1;
    }

    @Override
    public List<Dynamic> queryAll() {

        List<Dynamic> dynamics = baseMapper.selectList(new QueryWrapper<Dynamic>().orderByDesc("id")).stream()
                .map(dynamic -> {
                    List<Comments> comments = commentMapper.selectList(new QueryWrapper<Comments>()
                            .eq("dy_id", dynamic.getId()));
                    dynamic.setCommentsList(comments);
                    return dynamic;
                }).collect(Collectors.toList());
        dynamics.forEach(dynamic -> {
            isLiked(dynamic);
            queryUser(dynamic);
        });
        return dynamics;
    }

    private void queryUser(Dynamic dynamic) {
        String username=dynamic.getUsername();
        UserInfo one = userService.query().eq("username", username).select("avatar_url").one();
        dynamic.setAvatarUrl(one.getAvatarUrl());
    }

    @Override
    public Boolean like(long id) {
        String key=DY_LIKE+id;
        String username = UserHolder.getUser().getUsername();
        Double score = redisTemplate.opsForZSet().score(key, username);
        if(score==null){
            //未点赞，可以点赞
            boolean isSuccess = update().setSql("likes=likes+1").eq("id", id).update();
            if(isSuccess){
                redisTemplate.opsForZSet().add(key,username,System.currentTimeMillis());
            }
        }else{
            //已点赞，取消点赞
            boolean isSuccess = update().setSql("likes=likes-1").eq("id", id).update();
            if(isSuccess){
                redisTemplate.opsForZSet().remove(key,username);
            }
        }
        return true;
    }

    @Override
    public ScrollResult scroll(long max, Integer offset) {
        System.out.println("max:"+max+"offset"+offset);
        String username=UserHolder.getUser().getUsername();
        String key=FEED+username;
        Set<ZSetOperations.TypedTuple<String>> zTuple = redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key,
                0, max, offset, 2);
        if(zTuple.isEmpty()){
            return null;
        }
        List<Long> ids=new ArrayList<>();
        long minTime=0;
        int os=1;
        for(ZSetOperations.TypedTuple<String> tuple: zTuple){
            ids.add(Long.valueOf(tuple.getValue()));
            long time = tuple.getScore().longValue();
            if(time==minTime){
                os++;
            }else{
                minTime=time;
                os=1;
            }
        }

        String istr = StrUtil.join(",", ids);
        List<Dynamic> ds = query().in("id", ids).last("ORDER BY FIELD(id," + istr + ")").list();
        ds.forEach(d->{
            isLiked(d);
            queryUser(d);
        });
        ScrollResult scrollResult = new ScrollResult();
        scrollResult.setMinTime(minTime).setList(ds).setOffset(os);
        System.out.println(scrollResult);
        return scrollResult;
    }

    private void isLiked(Dynamic dynamic){
        LoginFormDTO user = UserHolder.getUser();
        if(user==null){
            return;
        }
        String username = user.getUsername();
        String key=DY_LIKE+dynamic.getId();
        Double score = redisTemplate.opsForZSet().score(key, username);
        dynamic.setIsLike(score!=null);
    }
}
